#include <iostream>
#include <vector>

using namespace std;

void radix_sort(vector<int> &vec)
{
    int len = vec.size();
    //寻找数组中的最大数
    int maxNum = vec[0];
    for(int i = 1; i < len; i++)
    {
        if(vec[i] > maxNum)
            maxNum = vec[i];
    }

    //统计位数
    int base = 1;
    while(maxNum / base > 0)
    {
        //计数
        vector<int> buckets(10); //定义10个桶i:0~9
        for(int i = 0; i < len; i++)
        {
            buckets[vec[i] / base % 10]++; //计数每个桶装入的元素数。注意：vec[i] / base % 10 是桶的下标 
        }

        //统计
        for(int i = 1; i < 10; i++)
        {
            buckets[i] += buckets[i - 1];
        }

        //存放
        vector<int> vecTemp(len); //计数、统计和存放和之前的计数排序有点类似，方法是一样的
        for(int i = len - 1; i >= 0; i--) //i = len - 1,不是i = len;一定要从后往前存放，比如原数组有3,12,3，如果从桶中前往后存放会影响两个3的前后顺序，在收集的时候出现不稳定排序
        {
            vecTemp[buckets[vec[i] / base % 10 ] - 1] = vec[i];
            buckets[vec[i] / base % 10]--; 
        }

        //将临时数组中的数放回原数组
        swap(vec, vecTemp);

        base *= 10;
    }
}

int main()
{
    int num;
    cin >> num;

    vector<int> vec;
    int temp;
    for(int i = 0; i < num; i++)
    {
        cin >> temp;
        vec.push_back(temp);
    }

    radix_sort(vec);

    for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}
